const LAST_CONNECTED_DEVICE = 'last_connected_device'
const PrinterJobs = require('../../printer/printerjobs')
const printerUtil = require('../../printer/printerutil')
const QR = require("../../utils/lib/qrcode")
var api = require('./../../config/api');

const app=getApp()
var util = require('./../../utils/util');


function inArray(arr, key, val) {
  for (let i = 0; i < arr.length; i++) {
    if (arr[i][key] === val) {
      return i
    }
  }
  return -1
}

// ArrayBuffer转16进度字符串示例
function ab2hex(buffer) {
  const hexArr = Array.prototype.map.call(
    new Uint8Array(buffer),
    function (bit) {
      return ('00' + bit.toString(16)).slice(-2)
    }
  )
  return hexArr.join(',')
}

function str2ab(str) {
  // Convert str to ArrayBuff and write to printer
  let buffer = new ArrayBuffer(str.length)
  let dataView = new DataView(buffer)
  for (let i = 0; i < str.length; i++) {
    dataView.setUint8(i, str.charAt(i).charCodeAt(0))
  }
  return buffer;
}

Page({
  data: {
    devices: [],
    connected: false,
    chs: [],
    codeSize: 160,
    version: app.globalData.version,
    account: "",
    password: "",
    t1:"",
  },
  onUnload() {
    this.closeBluetoothAdapter()
  },
  openBluetoothAdapter() {
    if (!wx.openBluetoothAdapter) {
      wx.showModal({
        title: '提示',
        content: '当前微信版本过低，无法使用该功能，请升级到最新微信版本后重试。'
      })
      return
    }
    wx.openBluetoothAdapter({
      success: (res) => {
        console.log('openBluetoothAdapter success', res)
        this.startBluetoothDevicesDiscovery()
      },
      fail: (res) => {
        console.log('openBluetoothAdapter fail', res)
        if (res.errCode === 10001) {
          wx.showModal({
            title: '错误',
            content: '未找到蓝牙设备, 请打开蓝牙后重试。',
            showCancel: false
          })
          wx.onBluetoothAdapterStateChange((res) => {
            console.log('onBluetoothAdapterStateChange', res)
            if (res.available) {
              // 取消监听，否则stopBluetoothDevicesDiscovery后仍会继续触发onBluetoothAdapterStateChange，
              // 导致再次调用startBluetoothDevicesDiscovery
              wx.onBluetoothAdapterStateChange(() => {
              });
              this.startBluetoothDevicesDiscovery()
            }
          })
        }
      }
    })
    wx.onBLEConnectionStateChange((res) => {
      // 该方法回调中可以用于处理连接意外断开等异常情况
      console.log('onBLEConnectionStateChange', `device ${res.deviceId} state has changed, connected: ${res.connected}`)
      this.setData({
        connected: res.connected
      })
      if (!res.connected) {
        wx.showModal({
          title: '错误',
          content: '蓝牙连接已断开',
          showCancel: false
        })
      }
    });
  },
  getBluetoothAdapterState() {
    wx.getBluetoothAdapterState({
      success: (res) => {
        console.log('getBluetoothAdapterState', res)
        if (res.discovering) {
          this.onBluetoothDeviceFound()
        } else if (res.available) {
          this.startBluetoothDevicesDiscovery()
        }
      }
    })
  },
  startBluetoothDevicesDiscovery() {
    if (this._discoveryStarted) {
      return
    }
    this._discoveryStarted = true
    wx.startBluetoothDevicesDiscovery({
      success: (res) => {
        console.log('startBluetoothDevicesDiscovery success', res)
        this.onBluetoothDeviceFound()
      },
      fail: (res) => {
        console.log('startBluetoothDevicesDiscovery fail', res)
      }
    })
  },
  stopBluetoothDevicesDiscovery() {
    wx.stopBluetoothDevicesDiscovery({
      complete: () => {
        console.log('stopBluetoothDevicesDiscovery')
        this._discoveryStarted = false
      }
    })
  },
  onBluetoothDeviceFound() {
    wx.onBluetoothDeviceFound((res) => {
      res.devices.forEach(device => {
        if (!device.name && !device.localName) {
          return
        }
        const foundDevices = this.data.devices
        const idx = inArray(foundDevices, 'deviceId', device.deviceId)
        const data = {}
        if (idx === -1) {
          data[`devices[${foundDevices.length}]`] = device
        } else {
          data[`devices[${idx}]`] = device
        }
        this.setData(data)
      })
    })
  },
  createBLEConnection(e) {
    const ds = e.currentTarget.dataset
    const deviceId = ds.deviceId
    const name = ds.name
    this._createBLEConnection(deviceId, name)
  },
  _createBLEConnection(deviceId, name) {
    wx.showLoading()
    wx.createBLEConnection({
      deviceId,
      success: () => {
        console.log('createBLEConnection success');
        this.setData({
          connected: true,
          name,
          deviceId,
        })
        this.getBLEDeviceServices(deviceId)
        wx.setStorage({
          key: LAST_CONNECTED_DEVICE,
          data: name + ':' + deviceId
        })
      },
      complete() {
        wx.hideLoading()
      },
      fail: (res) => {
        console.log('createBLEConnection fail', res)
      }
    })
    this.stopBluetoothDevicesDiscovery()
  },
  closeBLEConnection() {
    wx.closeBLEConnection({
      deviceId: this.data.deviceId
    })
    this.setData({
      connected: false,
      chs: [],
      canWrite: false,
      canQrcodWrite: false
    })
  },
  accountnput:function(e)
  {
    this.setData({
      account: e.detail.value
    })
  },
  passwordInput:function(e)
  {
    this.setData({
      password: e.detail.value
    })
  },
  loginToBluePrinter(){
    if (this.data.account == '' || this.data.password == '') {
      wx.showToast({
        title: '请输入账号和密码',
        icon:'none'
      })
      return
    }
    wx.setStorageSync('p_account', this.data.account)
    wx.setStorageSync('p_password', this.data.password)
    let t1 = setInterval(this.printReq, 1000 * 10)
    this.setData({
      t1:t1
    })
    wx.showToast({
      title: '登录成功，订单会自动打印',
      icon:'none'
    })
  },
  printReq(){
    let that = this

    if (!this.data.connected) {
      clearInterval(this.data.t1)
      return
    }

    let params = {}
    params.account = this.data.account
    params.password = this.data.password
    util.myRequest(api.getPrinterOrder, params, function(response) {
      console.log(response)
      let data = response.data
      if (!data.has_order) {
        return
      }
      that.printOrder(data)
		});
  },
  printOrder(data){
    let order = data.order
    let that = this
    order.forEach(item => {
      setTimeout(() => {
        let printerJobs = new PrinterJobs();
        let job = printerJobs
          // .print('小票订单')
          // .print('2020年09月22日17:34')
          .print(printerUtil.fillLine())
          .setAlign('ct')
          .setSize(2, 2)
          .print(data.shop.shop_name)
          // .setSize(1, 1)
          // .print('切尔西Chelsea')
          // .setSize(2, 2)
          // .print('在线支付(已支付)')
          .setSize(1, 1)
          .print('订单号：' + item.order_sn)
          .print(item.add_time)
          .setAlign('lt')
          .print(printerUtil.fillAround('订单明细'));
          item.detail.forEach(item2 => {

            item2.spec_name = ''
            if (item2.specification_name != "") {
              item2.spec_name = '('
              let arr = JSON.parse(item2.specification_name)
              arr.forEach(item3 => {
                item2.spec_name += item3 + ','
              })
              item2.spec_name = item2.spec_name.substr(0,item2.spec_name.length - 1) + ')'
            }

            job.print(printerUtil.inline(item2.food_name + item2.spec_name + ' * ' + item2.num, item2.price_pay))
          })
          
          // .print(printerUtil.fillAround('其他'))
          // .print('餐盒费：1')
          // .print('[赠送康师傅冰红茶] * 1')
          job.print(printerUtil.fillLine())
          .setAlign('rt')
          .print('原价：￥' + item.price_pay)
          .print('总价：￥' + item.price_pay)
          .setAlign('lt')
          .print(printerUtil.fillLine());
          if(item.remark != ""){
            job.print('备注：')
            .print(item.remark)
            .print(printerUtil.fillLine())
          }
          job.print('客户地址：' + item.address_info.address)
          .print('客户电话：' + item.address_info.phone)
          // .printBar('12345678')
          // .println();

        let buffer = printerJobs.buffer();
        // console.log('ArrayBuffer', 'length: ' + buffer.byteLength, ' hex: ' + ab2hex(buffer));
        // 1.并行调用多次会存在写失败的可能性
        // 2.建议每次写入不超过20字节
        // 分包处理，延时调用
        const maxChunk = 20;
        const delay = 10;
        for (let i = 0, j = 0, length = buffer.byteLength; i < length; i += maxChunk, j++) {
          let subPackage = buffer.slice(i, i + maxChunk <= length ? (i + maxChunk) : length);
          that._writeBLECharacteristicValue(subPackage)
          // setTimeout(this._writeBLECharacteristicValue, 1, subPackage);//有问题时在加延迟
        }
        
        let printerJobs2 = new PrinterJobs();
        //二维码打印测试
        // printerJobs.print('二维码打印测试');
        printerJobs2.setAlign('CT')//设置二维码显示位置  居中
        QR.api.draw("https://shop.sbedian.com/wechat/xytCodeGetFood?id=1-"+item.order_sn, "edit_area_canvas", that.data.codeSize, that.data.codeSize, this, null);
        wx.canvasGetImageData({
          canvasId: 'edit_area_canvas',
          x: 0,
          y: 0,
          width: that.data.codeSize,
          height: that.data.codeSize,
          success: function (res) {
            printerJobs2.printQrcode(res).println();
          },
          complete: function (res) {
            let buffer = printerJobs2.buffer();
            //console.log('ArrayBuffer', 'length: ' + buffer.byteLength, ' hex: ' + ab2hex(buffer));
            const maxChunk = 20;
            for (let i = 0, j = 0, length = buffer.byteLength; i < length; i += maxChunk, j++) {
              let subPackage = buffer.slice(i, i + maxChunk <= length ? (i + maxChunk) : length);
              that._writeBLECharacteristicValue(subPackage);
            }
            printerJobs2.println();
            console.log('ArrayBuffer', 'length: ' + buffer.byteLength, ' hex: ' + ab2hex(buffer));
          }
        })

      }, 100);
    })
  },
  getBLEDeviceServices(deviceId) {
    wx.getBLEDeviceServices({
      deviceId,
      success: (res) => {
        console.log('getBLEDeviceServices', res)
        for (let i = 0; i < res.services.length; i++) {
          if (res.services[i].isPrimary) {
            this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid)
            return
          }
        }
      }
    })
  },
  getBLEDeviceCharacteristics(deviceId, serviceId) {
    wx.getBLEDeviceCharacteristics({
      deviceId,
      serviceId,
      success: (res) => {
        console.log('getBLEDeviceCharacteristics success', res.characteristics)
        // 这里会存在特征值是支持write，写入成功但是没有任何反应的情况
        // 只能一个个去试
        for (let i = 0; i < res.characteristics.length; i++) {
          const item = res.characteristics[i]
          if (item.properties.write) {
            this.setData({
              canWrite: true,
              canQrcodWrite: true
            })
            this._deviceId = deviceId
            this._serviceId = serviceId
            this._characteristicId = item.uuid
            break;
          }
        }
      },
      fail(res) {
        console.error('getBLEDeviceCharacteristics', res)
      }
    })
  },
  writeBLECharacteristicValue() {
    let printerJobs = new PrinterJobs();
    let that = this
    printerJobs
      .print('小票订单')
      .print('2020年09月22日17:34')
      .print(printerUtil.fillLine())
      .setAlign('ct')
      .setSize(2, 2)
      .print('#20饿了么外卖')
      .setSize(1, 1)
      .print('切尔西Chelsea')
      .setSize(2, 2)
      .print('在线支付(已支付)')
      .setSize(1, 1)
      .print('订单号：5415221202244734')
      .print('2020-09-07 18:08:08')
      .setAlign('lt')
      .print(printerUtil.fillAround('一号口袋'))
      .print(printerUtil.inline('意大利茄汁一面 * 1', '15'))
      .print(printerUtil.fillAround('其他'))
      .print('餐盒费：1')
      .print('[赠送康师傅冰红茶] * 1')
      .print(printerUtil.fillLine())
      .setAlign('rt')
      .print('原价：￥16')
      .print('总价：￥16')
      .setAlign('lt')
      .print(printerUtil.fillLine())
      .print('备注')
      .print("无")
      .print(printerUtil.fillLine())
      .printBar('12345678')
      .println();

    let buffer = printerJobs.buffer();
    console.log('ArrayBuffer', 'length: ' + buffer.byteLength, ' hex: ' + ab2hex(buffer));
    // 1.并行调用多次会存在写失败的可能性
    // 2.建议每次写入不超过20字节
    // 分包处理，延时调用
    const maxChunk = 20;
    const delay = 10;
    for (let i = 0, j = 0, length = buffer.byteLength; i < length; i += maxChunk, j++) {
      let subPackage = buffer.slice(i, i + maxChunk <= length ? (i + maxChunk) : length);
      that._writeBLECharacteristicValue(subPackage)
      // setTimeout(this._writeBLECharacteristicValue, 10, subPackage);//有问题时在加延迟
    }
  },

  writeQrCodeBLECharacteristicValue() {
    let printerJobs = new PrinterJobs();
    let that = this
    //二维码打印测试
    printerJobs.print('二维码打印测试');
   // printerJobs.setAlign('CT')//设置二维码显示位置  居中
    QR.api.draw("https://www.baidu.com", "edit_area_canvas", that.data.codeSize, that.data.codeSize, this, null);
    wx.canvasGetImageData({
      canvasId: 'edit_area_canvas',
      x: 0,
      y: 0,
      width: that.data.codeSize,
      height: that.data.codeSize,
      success: function (res) {
        printerJobs.printQrcode(res).println();
      },
      complete: function (res) {
        let buffer = printerJobs.buffer();
        //console.log('ArrayBuffer', 'length: ' + buffer.byteLength, ' hex: ' + ab2hex(buffer));
        const maxChunk = 20;
        for (let i = 0, j = 0, length = buffer.byteLength; i < length; i += maxChunk, j++) {
          let subPackage = buffer.slice(i, i + maxChunk <= length ? (i + maxChunk) : length);
          that._writeBLECharacteristicValue(subPackage);
        }
        console.log('ArrayBuffer', 'length: ' + buffer.byteLength, ' hex: ' + ab2hex(buffer));
      }
    })

  },
  _writeBLECharacteristicValue(buffer) {
    wx.writeBLECharacteristicValue({
      deviceId: this._deviceId,
      serviceId: this._serviceId,
      characteristicId: this._characteristicId,
      value: buffer,
      success(res) {
        console.log('writeBLECharacteristicValue success', res)
      },
      fail(res) {
        console.log('writeBLECharacteristicValue fail', res)
      }
    })
  },
  closeBluetoothAdapter() {
    wx.closeBluetoothAdapter()
    this._discoveryStarted = false
  },
  onLoad(options) {
    const lastDevice = wx.getStorageSync(LAST_CONNECTED_DEVICE);
    this.setData({
      lastDevice: lastDevice
    })
    let account = wx.getStorageSync('p_account')
    let password = wx.getStorageSync('p_password')
    if (account != "") {
      this.setData({
        account: account,
        password: password,
      })
    }
  },
  createBLEConnectionWithDeviceId(e) {
    // 小程序在之前已有搜索过某个蓝牙设备，并成功建立连接，可直接传入之前搜索获取的 deviceId 直接尝试连接该设备
    const device = this.data.lastDevice
    if (!device) {
      return
    }
    const index = device.indexOf(':');
    const name = device.substring(0, index);
    const deviceId = device.substring(index + 1, device.length);
    console.log('createBLEConnectionWithDeviceId', name + ':' + deviceId)
    wx.openBluetoothAdapter({
      success: (res) => {
        console.log('openBluetoothAdapter success', res)
        this._createBLEConnection(deviceId, name)
      },
      fail: (res) => {
        console.log('openBluetoothAdapter fail', res)
        if (res.errCode === 10001) {
          wx.showModal({
            title: '错误',
            content: '未找到蓝牙设备, 请打开蓝牙后重试。',
            showCancel: false
          })
          wx.onBluetoothAdapterStateChange((res) => {
            console.log('onBluetoothAdapterStateChange', res)
            if (res.available) {
              // 取消监听
              wx.onBluetoothAdapterStateChange(() => {
              });
              this._createBLEConnection(deviceId, name)
            }
          })
        }
      }
    })
  }
})